﻿/* $RCSFile: CrmAuthenticationBase.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/CRMWrapper3/Authentication/CrmAuthenticationBase.cs $
 * $log$
 * Revision 19 2011/02/22 01:23:08  christian.surieux
 *   V4 Migration 22/2/11
 * Revision 19 2011/02/22 01:22:26  christian.surieux
 *   V4 Migration 22/2/11
 * Revision 6 2010/08/06 19:56:32  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using AddonNice.CRMWrapper;
using AddonNice.CRMWrapper.CRM4ADDisco;
using AddonNice.Settings;
using System.Net;
using System.Globalization;
using AddonNice.CRMWrapper.CRM4Server;
using System.Web.Services.Protocols;

namespace AddonNice.CRMWrapper.Authentication
{
    public abstract class CrmAuthenticationBase
    {
        #region discovery service main properties

        /// <summary>
        /// Admin CRM account
        /// </summary>
        protected string _CRMServiceAccount                 =   Config.CRMServiceAccount; 
        protected string _CRMServicePassword                =   Config.CRMServicePassword; 
        protected string _CRMServiceDomain                  =   Config.CRMServiceDomain;

        /// <summary>
        /// Default eg anonymous CRM account
        /// </summary>
        protected string _CRMServiceDefaultAccount          =   Config.CRMDefaultAccount;
        protected string _CRMServiceDefaultPassword         =   Config.CRMDefaultAccountPassword;
        protected string _CRMServiceDefaultDomain           =   Config.CRMDefaultAccountDomain;

        /// <summary>
        /// PrivateUser Group member
        /// </summary>
        protected string _CRMPrivAccount                    =   Config.CRMPrivAccount;
        protected string _CRMPrivPassword                   =   Config.CRMPrivPassword;
        protected string _CRMPrivDomain                     =   Config.CRMPrivDomain;

        /// <summary>
        /// Admin CRM account
        /// </summary>
        public virtual string CRMServiceAccount
        { get{  return _CRMServiceAccount;} set{ _CRMServiceAccount=value;} }
        public virtual string CRMServicePassword
        { get{  return _CRMServicePassword;} set{ _CRMServicePassword=value;} }
        public virtual string CRMServiceDomain
        { get{  return _CRMServiceDomain;} set{ _CRMServiceDomain=value;} }

        /// <summary>
        /// Default eg anonymous CRM account
        /// </summary>
        public virtual string CRMServiceDefaultAccount
        { get{  return _CRMServiceDefaultAccount;} set{ _CRMServiceDefaultAccount=value;} }
        public virtual string CRMServiceDefaultPassword
        { get{  return _CRMServiceDefaultPassword;} set{ _CRMServiceDefaultPassword=value;} }
        public virtual string CRMServiceDefaultDomain
        { get{  return _CRMServiceDefaultDomain;} set{ _CRMServiceDefaultDomain=value;} }

        /// <summary>
        /// PrivateUser Group member
        /// </summary>
        public virtual string CRMPrivAccount
        { get{  return _CRMPrivAccount;} set{ _CRMPrivAccount=value;} }
        public virtual string CRMPrivPassword
        { get{  return _CRMPrivPassword;} set{ _CRMPrivPassword=value;} }
        public virtual string CRMPrivDomain
        { get{  return _CRMPrivDomain;} set{ _CRMPrivDomain=value;} }


        protected string _ServiceUrl    =   string.Empty;
        public virtual string ServiceUrl
        {
            get
            {
                return _ServiceUrl;
            }
            set
            {
                _ServiceUrl    =   value;
            }
        }
        
        protected string _MetaDataServiceUrl    =   string.Empty;
        public virtual string MetaDataServiceUrl
        {
            get
            {
                return _MetaDataServiceUrl;
            }
            set
            {
                _MetaDataServiceUrl    =   value;
            }
        }

        string _onlineTicket                        =   string.Empty;
        public virtual string onlineTicket
        {
            get
            {
                return _onlineTicket;
            }
        }

        protected  OrganizationDetail _Organization =   null;
       
        public virtual OrganizationDetail Organization
        {
            get
            {
                return _Organization;
            }
            set
            {
                _Organization   =   value;
            }
        }

        protected int _Port    =   80;
        public virtual int Port
        {
            get
            {
                return _Port;
            }
            set
            {
                if ( value > 0 )
                    _Port   =   value;
            }
        }
        
        protected string _DiscoServerName  =   "localhost";
        public virtual string DiscoServerName
        {
            get
            {
                return _DiscoServerName;
            }
            set
            {
                if ( value != string.Empty )
                    _DiscoServerName =   value;
            }
        }
        
        protected string _WebApplicationUrl =   string.Empty;
        public virtual string WebApplicationUrl
        {
            get
            {
                return _WebApplicationUrl;
            }
            set
            {
                _WebApplicationUrl    =   value;
            }
        }

        protected string _OrganizationName  =   string.Empty;
        public virtual string OrganizationName
        {
            get
            {
                return _OrganizationName;
            }
            set
            {
                _OrganizationName   =   value;
            }
        }

        protected string _OrganizationFriendlyName  =   string.Empty;
        public virtual string OrganizationFriendlyName
        {
            get
            {
                return _OrganizationFriendlyName;
            }
            set
            {
                _OrganizationFriendlyName   =   value;
            }
        }

        protected Guid _OrganizationId   =   Guid.Empty;
        public Guid OrganizationId
        {
            get
            {
                return _OrganizationId;
            }
            set
            {
                _OrganizationId    =   value;
            }
        }
        
        protected CrmDiscoveryService _CrmDisco;

        public abstract CrmDiscoveryService CrmDisco
        { get;  }

        #endregion discovery service main properties

        #region urls for discovery service
        
        public abstract string UrlDisco
        { get; }
        
        #endregion urls for discovery service

        public virtual byte[] DownLoadFile(string url,ref bool OkDownload)
        { return null; }

        public abstract bool FindOrganization(string orgName);

        public abstract bool IsUserOk4Crm(string domain,string login,string pwd);

        
        public List<OrganizationDetail> _Organizations =   null;
        /// <summary>
        /// Retrieve with disco service list of all org managed on this CRM server
        /// </summary>
        public abstract List<OrganizationDetail> Organizations
        {   get;}

        #region accessors to CRM services

        public Crm4WebService userService4
        {
            get
            {
                return userService as Crm4WebService;
            }
        }

        public Crm4WebService adminService4
        {
            get
            {
                return adminService as Crm4WebService;
            }
        }

        public Crm4WebService adminAdminService4
        {
            get
            {
                return adminAdminService as Crm4WebService;
            }
        }

        protected CrmWebService _userService    =   null;
        public virtual CrmWebService userService
        {
            get
            {
                if (_userService == null)
				{
					if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( "[E]CRMWrapperBase _userService null",CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException("-userService null");
				}
                return _userService;
            }
        }


        protected CrmMetadataWebService _userMetaService    =   null;
        public virtual CrmMetadataWebService userMetaService
        {
            get
            {
                if ( _userMetaService == null)
				{
					if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( "[E]CRMWrapperBase _userMetaService null",CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException("_userMetaService null");
				}
                return _userMetaService;
            }
        }

        protected CrmWebService _adminService               =   null;
        public virtual CrmWebService adminService
        {
            get
            {
                if ( _adminService == null )
				{
					if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( "[E]CRMWrapperBase _adminService null",CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException("_adminService null");
				}
                return _adminService;
            }
        }

        protected CrmWebService _adminAdminService          =   null;
        public virtual CrmWebService adminAdminService
        {
            get
            {
                if (_adminAdminService == null)
				{
					if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( "[E]CRMWrapperBase _adminAdminService null",CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException("_adminAdminService null");
				}
                return _adminAdminService;
            }
        }

        protected CrmMetadataWebService _adminMetaService   =   null;
        public CrmMetadataWebService adminMetaService
        {
            get
            {
                if ( _adminMetaService == null )
				{
					if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( "[E]CRMWrapperBase _adminMetaService null",CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException("_adminMetaService null");
				}
                return _adminMetaService;
            }
        }

        #endregion accessors to CRM services

        /// <summary>
        /// Called by Ctor to create Admin crmservice objects necessary to first Crm calls with admin mode
        /// </summary>
        public abstract void InitAdminService(bool UsePreAuthenticate);
        /// <summary>
        /// Called by startWrapper to create different crmservice objects necessary to further running
        /// </summary>
        public abstract void InitServices(bool UsePreAuthenticate);

        protected Guid _userId                              =   Guid.Empty;
        /// <summary>
		/// The Guid corresponding to the authentified user, obtained with whoAmI using userService
		/// </summary>
        public virtual Guid userId
        {
            get
            {
                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmAuthenticationBase userId BEG _userId Empty: '{0}'", _userId == Guid.Empty),CRMTraceSwitch.Sw.Info);
                if (_userId == Guid.Empty)
                {
                    try
                    {
                        WhoAmIRequest request1		=   new WhoAmIRequest();
                        if (CRMTraceSwitch.Sw.TraceVerbose)
                        {
                            if ( userService4.Credentials is System.Net.NetworkCredential )
                                Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, "[V]CrmAuthenticationBase userId NetworkCredentialsUserName: '{0}'",
                                 ((NetworkCredential)userService4.Credentials).UserName), CRMTraceSwitch.Sw.Info);
                            else
                                Trace.WriteLine("[V]CrmAuthenticationBase userId UserName empty.", CRMTraceSwitch.Sw.Info);
                        }
                        WhoAmIResponse response1	=   (WhoAmIResponse)userService4.ExecuteRaw(request1);
                        _userId						=   response1.UserId;
						// we should have a dynamic typeCode here
                        if ( CRMTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmAuthenticationBase userId GET END WhoAmI Ok _userId: '{0}'", _userId),CRMTraceSwitch.Sw.Info);
                    }
                    catch (SoapException sx)
                    {
                        string msg      =   string.Format("[E]CrmAuthenticationBase userId GET ex: {0}-{1}", sx, sx.Detail.InnerText);
                        if ( CRMTraceSwitch.Sw.TraceError )
                            Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                        throw new CRMWrapperException(msg, sx);
                    }
                    catch (CRMWrapperException )
                    {
                        throw;
                    }
                    catch (Exception ex)
                    {
                        string msg      =   string.Format("[E]CrmAuthenticationBase userId GET ex: {0}", ex);
                        if ( CRMTraceSwitch.Sw.TraceError )
                            Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                        throw new CRMWrapperException(msg, ex);
                    }
                }
                return _userId;
            }
			set
			{
				_userId						=   value;
				// we should have a dynamic typeCode here
                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmAuthenticationBase userId SET: {0}", _userId),CRMTraceSwitch.Sw.Info);
			}
        }
        
        protected ADNDynSystemUser _sysUser                     =   null; // crm user retrieved with WhoAmI Api
        /// <summary>
        /// SystemUser corresponding to the authentified user
		/// </summary>
        public ADNDynSystemUser sysUser
        {
            get
            {
                if (_sysUser == null)
                    GetUser();
                return _sysUser;
            }
			set
			{
                _sysUser	=	value;
				// we should have a dynamic typeCode here
                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmAuthenticationBase sysUser set fullname: {0}", _sysUser.fullname),CRMTraceSwitch.Sw.Info);
			}
        }

        /// <summary>
        /// Get the systemuser entity from the userid by calling RetrieveSystemUser API
        /// Set it in _SysUser, 
		/// _SysUser is determined by userid
        /// </summary>
        public ADNDynSystemUser GetUser()
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmAuthenticationBase GetUser BEG _sysUser != null: {0}", _sysUser != null),CRMTraceSwitch.Sw.Info);
            if ( _sysUser != null )
                return _sysUser;
            try
            {
                ADNDynSystemUser sUser              =   new ADNDynSystemUser(Wrapper,userId);
                if ( sUser.adminRetrieve() )
                {
                    sysUser							=   sUser;
                    if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmAuthenticationBase GetUser END domainname: {0}, fullname: {1}", _sysUser.domainname,_sysUser.fullname),CRMTraceSwitch.Sw.Info);
					return _sysUser;
				}
            }
            catch (SoapException sx)
            {
                string msg                          =   string.Format("[E]CrmAuthenticationBase GetUser ex: {0}-{1}", sx, sx.Detail.InnerText);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine(msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, sx);
            }
            catch (CRMWrapperException)
            {
                throw;
            }
            catch (Exception ex)
            {
                string msg  =   string.Format("[E]CrmAuthenticationBase GetUser ex: {0}", ex);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, ex);
            }
            const string msgex  =   "[E]CrmAuthenticationBase GetUser failed.";
            if ( CRMTraceSwitch.Sw.TraceError )
                Trace.WriteLine(msgex,CRMTraceSwitch.Sw.Info);
			throw new CRMWrapperException(msgex);
        }

		/// <summary>
		/// Current user name
		/// </summary>
        public string userName
        {
            get
            {
                if ( _sysUser != null)
                    return _sysUser.domainname;
                return string.Empty;
            }
        }

        /// <summary>
        /// Find user by its CRM Guid
        /// </summary>
        public ADNDynSystemUser GetUserById2(Guid uId)
        {
    		if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmAuthenticationBase GetUserById2 BEG UserId : {0}", uId),CRMTraceSwitch.Sw.Info);
            ADNDynSystemUser currentUser		    =   null;
            try
            {
                currentUser                         =   new ADNDynSystemUser(Wrapper,uId);
                bool success                        =   currentUser.adminRetrieve();
				if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmAuthenticationBase GetUserById2 UserId : {0} - {1}", uId,currentUser.domainname),CRMTraceSwitch.Sw.Info);
            }
            catch (SoapException sx)
            {
                string msg                          =   string.Format("[E]CrmAuthenticationBase GetUserById2 ex: {0}-{1}", sx, sx.Detail.InnerText);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, sx);
            }
            catch (CRMWrapperException)
            {
                throw;
            }
            catch (Exception ex)
            {
                string msg                          =   string.Format("[E]CrmAuthenticationBase GetUserById2 ex: {0}", ex);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, ex);
            }
            return currentUser;
        }

        /// <summary>
        /// Find user by its name
        /// </summary>
        public virtual ADNDynSystemUser GetUserByDomainName2(string name)
        {
            ADNDynSystemUser currentUser	    =   null;
            try
            {
                currentUser					=   Wrapper.Util.FindSystemUserByDomainName(name,true);
				if ( currentUser != null )
				{
					if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmAuthenticationBase GetUserByDomainName2 name: {0}, currentUser.domainname: '{1}'", name, currentUser.domainname),CRMTraceSwitch.Sw.Info);
					return currentUser;
				}
            }
            catch (SoapException sx)
            {
                string msg  =   string.Format("[E]CrmAuthenticationBase GetUserByDomainName2  ex: {0}-{1}", sx, sx.Detail.InnerText);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, sx);
            }
            catch (CRMWrapperException)
            {
                throw;
            }
            catch (Exception ex)
            {
                string msg  =   string.Format("[E]CrmAuthenticationBase GetUserByDomainName2 ex: {0}", ex);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, ex);
            }
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmAuthenticationBase GetUserByDomainName2 DomainName: {0}, currentUser null.", name),CRMTraceSwitch.Sw.Info);
            return null;
        }

        protected ADNDynSystemUser _adminSysUser                =   null;
        public ADNDynSystemUser InitAdminUser()
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmAuthenticationBase InitAdminUser BEG _adminSysUser != null : {0}",_adminSysUser != null),CRMTraceSwitch.Sw.Info);
            if ( _adminSysUser != null)
                return _adminSysUser;
            if ( CRMTraceSwitch.Sw.TraceVerbose)
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmAuthenticationBase InitAdminUser _adminUserId: {0}",adminUserId),CRMTraceSwitch.Sw.Info);
            try
            {
                ADNDynSystemUser sUser              =   new ADNDynSystemUser(Wrapper,_adminUserId);
                if ( sUser.adminRetrieve() )
                {
                    _adminSysUser                   =   sUser; 
                     if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmAuthenticationBase InitAdminUser retrieved from Crm _adminSysUser.domainname: {0}", _adminSysUser.domainname),CRMTraceSwitch.Sw.Info);
                }
            }
            catch (SoapException sx)
            {
                string msg  =   string.Format("[E]CrmAuthenticationBase InitAdminUser ex: {0}-{1}", sx, sx.Detail.InnerText);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg);
            }
            catch (CRMWrapperException)
            {
                throw;
            }
            catch (Exception ex)
            {
                string msg  =   string.Format("[E]CrmAuthenticationBase InitAdminUser ex: {0}", ex);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, ex);
            }
            return _adminSysUser;
        }

        protected Guid _adminUserId                         =   Guid.Empty;
		/// <summary>
		/// Guid of CRM administrator specified in config file
		/// </summary>
        public virtual Guid adminUserId
        {
            get
            {
                if ( _adminUserId == Guid.Empty )
                {
                    try
                    {
                        WhoAmIRequest request1      =   new WhoAmIRequest();
                        WhoAmIResponse response1    =   (WhoAmIResponse)adminAdminService4.ExecuteRaw(request1);
                        _adminUserId                =   response1.UserId;
                        InitAdminUser();
                        if ( CRMTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmAuthenticationBase adminUserId.get WhoAmI AdminUserName : {0}, _adminUserId : '{1}'", adminUserName, _adminUserId),CRMTraceSwitch.Sw.Info);
                    }
                    catch (SoapException sx)
                    {
                        string msg  =   string.Format("[E]CrmAuthenticationBase adminUserId.get ex: {0}-{1}", sx, sx.Detail.InnerText);
                        if ( CRMTraceSwitch.Sw.TraceError )
                            Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                        throw new CRMWrapperException(msg, sx);
                    }
                    catch (CRMWrapperException)
                    {
                        throw;
                    }
                    catch (Exception ex)
                    {
                        string msg  =   string.Format("[E]CrmAuthenticationBase adminUserId ex: {0}", ex);
                        if ( CRMTraceSwitch.Sw.TraceError )
                            Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                        throw new CRMWrapperException(msg, ex);
                    }
                }
                return _adminUserId;
            }
        }

        /// <summary>
        /// Domain name for the admin account
        /// </summary>
        public string adminUserName
        {
            get
            {
                if (_adminSysUser != null)
                    return _adminSysUser.domainname;
                return string.Empty;
            }
        }
        

        protected CrmWrapper4 Wrapper   =   null;
        public CrmAuthenticationBase(CrmWrapper4 wrp)
        {
            Wrapper =   wrp;
        }
   }
}
